﻿using LaoLuo;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Reflection;

namespace LaoLuo.Common.Test
{
    
    
    /// <summary>
    ///这是 CommonExtensionsTest 的测试类，旨在
    ///包含所有 CommonExtensionsTest 单元测试
    ///</summary>
    [TestClass()]
    public class CommonExtensionsTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///获取或设置测试上下文，上下文提供
        ///有关当前测试运行及其功能的信息。
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region 附加测试特性
        // 
        //编写测试时，还可使用以下特性:
        //
        //使用 ClassInitialize 在运行类中的第一个测试前先运行代码
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //使用 ClassCleanup 在运行完类中的所有测试后再运行代码
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //使用 TestInitialize 在运行每个测试前先运行代码
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //使用 TestCleanup 在运行完每个测试后运行代码
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///SetValidValue 的测试
        ///</summary>
        public void SetValidValueTestHelper<T>(T a, T b, T expected, Func<T, bool> IsValid = null)
        {
            a = a.GetValid(b, IsValid);
            Assert.AreEqual(expected, a);
        }

        [TestMethod()]
        public void SetValidValueTest()
        {
            SetValidValueTestHelper("a", " d", " d", s => !string.IsNullOrWhiteSpace(s));
            SetValidValueTestHelper("a", " ", "a", s => !string.IsNullOrWhiteSpace(s));
            SetValidValueTestHelper("a", "", "a");
            SetValidValueTestHelper("a", "d", "d");
        }

        /// <summary>
        ///GetValid 的测试
        ///</summary>
        public void GetValidTestHelper<T>(T a, T? b, Func<T, bool> isValid)
            where T : struct
        {
            var actual = CommonExtensions.GetValid<T>(a, b, isValid);
            Assert.AreEqual(a, actual);
        }

        [TestMethod()]
        public void GetValidTest()
        {
            int a = 100;
            int? b = 111;
            GetValidTestHelper(a, b, v => v > 1000);
        }

        /// <summary>
        ///A test for GetNondefaultPropCount
        ///</summary>
        public void GetNondefaultPropCountTestHelper<T>(T obj)
        {
            var actual = CommonExtensions.GetNondefaultPropCount<T>(obj);
            
        }

        [TestMethod()]
        public void GetNondefaultPropCountTest()
        {
            Assert.AreEqual(2, new School { Age = 100, Name = "2B" }.GetNondefaultPropCount());
            Assert.AreEqual(1, new School { Name = "2B" }.GetNondefaultPropCount());
        }

        public struct School
        {
            public string Name { get; set; }

            public int Age { get; set; }

            public List<SchoolClass> Classes { get; set; }

            public SchoolClass this[int index]
            {
                get
                {
                    return Classes[index];
                }
            }
        }

        public struct SchoolClass
        {
            public int Count { get; set; }

            public string Name { get; set; }

            private int Int1 { get; set; }

            public static int Int2 { get; set; }
        }

        /// <summary>
        ///GetValid 的测试
        ///</summary>
        public void GetValidTest1Helper<T>(T? a, IEnumerable<T?> b, Func<T, bool> IsValid = null)
            where T : struct
        {
            var actual = CommonExtensions.GetValid<T>(a, b, IsValid);
            Assert.AreEqual(1, actual);
        }

        [TestMethod()]
        public void GetValidTest1()
        {
            int? a = null;

            List<int?> b = new List<int?>() { null, null, 1 };

            GetValidTest1Helper(a, b); //, i=>i>100
        }

        /// <summary>
        ///ToDayOfWeek 的测试
        ///</summary>
        [TestMethod()]
        public void ToDayOfWeekTest()
        {
            Assert.AreEqual(DayOfWeek.Sunday, 00.ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Monday, 01.ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Tuesday, 02.ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Wednesday, 03.ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Thursday, 04.ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Friday, 05.ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Saturday, 06.ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Sunday, 07.ToDayOfWeek());

            Assert.AreEqual(DayOfWeek.Sunday, "00".ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Monday, "01".ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Tuesday, "02".ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Wednesday, "03".ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Thursday, "04".ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Friday, "05".ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Saturday, "06".ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Sunday, "07".ToDayOfWeek());

            Assert.AreEqual(DayOfWeek.Sunday, "日".ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Monday, "一".ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Tuesday, "二".ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Wednesday, "三".ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Thursday, "四".ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Friday, "五".ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Saturday, "六".ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Monday, "周一".ToDayOfWeek());

            Assert.AreEqual(DayOfWeek.Tuesday, "星期二".ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Sunday, "星期日".ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Sunday, "星期天".ToDayOfWeek());

            Assert.AreEqual(DayOfWeek.Tuesday, "周二".ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Sunday, "周日".ToDayOfWeek());
            Assert.AreEqual(DayOfWeek.Sunday, "周天".ToDayOfWeek());

            Assert.AreEqual(DayOfWeek.Sunday, "Sunday".ToDayOfWeek());

            Assert.AreEqual(DateTime.Now.DayOfWeek, DateTime.Now.ToDayOfWeek());
        }

        [TestMethod()]
        public void GetHashCodeTest()
        {
            var s1 = new School() { Age = 100, Name = "S1" };
            var s2 = new School() { Age = 100, Name = "S2" };

            Assert.AreNotEqual(s1.GetHashCode(s1.Age, s1.Name), s2.GetHashCode(s2.Age, s2.Name));
        }

        /// <summary>
        ///GetPropertiesInstancePublic 的测试
        ///</summary>
        [TestMethod()]
        public void GetPropertiesInstancePublicTest()
        {
           var p = typeof(SchoolClass).GetProperties(BindingFlags.Instance | BindingFlags.Public);
           AssertHelper.AreEqual(new SchoolClass { Count = 100, Name = "class1" }.GetPropertiesInstancePublic(), p);
        }

        /// <summary>
        ///ToDictionary 的测试
        ///</summary>
        [TestMethod]
        public void ToDictionaryTest()
        {
            var sc = new SchoolClass { Count = 100, Name = "class1" }.ToDictionary();
            AssertHelper.AreEqual(sc.Keys, "Count", "Name", "Int1");
            AssertHelper.AreEqual(sc.Values, 100, "class1", 0);
        }

        /// <summary>
        ///ToObject 的测试
        ///</summary>
        public void ToObjectTestHelper<T>(IDictionary<string, object> dictionary, T value)
            where T : IComparable<T>, new()
        {
            Assert.IsTrue(value.Equals(dictionary.ToObject<T>()));
            Assert.AreEqual(0, value.CompareTo(dictionary.ToObject<T>()));
        }

        [TestMethod]
        public void ToObjectTest()
        {
            ToObjectTestHelper(
                new Dictionary<string, object>
                    {
                        {"Name", "chester"},
                        {"Value", 199}
                    },
                new Class1 {Name = "chester", Value = 199});
        }

        /// <summary>
        ///Extend 的测试
        ///</summary>
        public void ExtendTest1Helper<T>()
            where T : new()
        {
            var c1 = new Class1 { Name = "chester", Value = 199 };
            var c1Copy = new Class1 { Name = "chester", Value = 199 };
            var c2 = new Class1 { Value = 299 };
            var c22 = new Class1 { Name = "crow", Value = 399 };
            var c222 = new Class1 { Name = "", Value = 0 }; 

            var c3 = c1.Extend(c2, c22, c222);
            //var c3 = c1.Extend(c222);

            Assert.AreEqual(c3.Name, c22.Name);
            Assert.AreEqual(c3.Value, c22.Value);
            Assert.AreEqual(c1Copy, c1);
        }

        [TestMethod()]
        public void ExtendTest1()
        {
            ExtendTest1Helper<GenericParameterHelper>();
        }

        [TestMethod]
        public void ExtendTest()
        {
            var c1 = new Class1 { Name = "chester", Value = 199 };
            var c2 = new Class1 { Value = 299 };

            var c3 = c1.Extend(c2);

            Assert.AreEqual(c3.Name, c1.Name);
            Assert.AreEqual(c3.Value, c2.Value);
        }

        /// <summary>
        ///HasValidValue 的测试
        ///</summary>
        [TestMethod()]
        public void HasValidValueTest()
        {
            Assert.IsTrue(1.HasValidValue());
            Assert.IsTrue(!0.HasValidValue());

            Assert.IsTrue("abc".HasValidValue());
            Assert.IsTrue(!"".HasValidValue());
        }

        [TestMethod()]
        public void IsInTest()
        {
            Assert.IsTrue("abc".IsIn("abc", "bcd"));
            Assert.IsFalse("abc".IsIn("abcd", "bcd"));
            Assert.IsTrue(1.IsIn(1, 2, 3));
            Assert.IsFalse(1.IsIn(3, 4, 5));
            Assert.IsFalse("ab".IsIn());
        }
    }
}
